##
## Htgroup.py 
##
## Controls user access, passwords, etc. for htpasswd/htgroup
##
##
## Author: Shannon Eric Peevey <speeves@erikin.com>, 17 Jan 2004
##

import os
import re
import Webcontrol
import Mysql

class HtgroupFunc:
    """This class offers user admin functionality to the
	cwsAdmin.py script"""

    def CreateUsers(self, config, utilityObject):
        """ create a user account with username:password and add them to a web
	uses apache htpasswd to generate the database file """

        ## DEBUGGING
        if config['General']["debugLevel"] == '5':
            import pdb; pdb.set_trace()

        objectName = "Username? (q => finish) [q] "
        # grab single/multiple groupNames
        userList = utilityObject.GetObjectId(config, objectName)

        failedUserArray =[]
        # loop through userList to generate passwords and add them to webs
        for user in userList:
            # changes the password
            self.ChangePassword(config, utilityObject, user)
            ###### end of password file manip
            
            # instantiate instance of output to grab a list of
            # vhosts that are available
            output = Webcontrol.ApacheFunc()
        
            # add user to htgroup file
            htgroup = self.BuildHtgroupFileName(config, utilityObject, output)

            try:
                # append the value of the user to the correct htgroup file
                self.HtgroupAppend(htgroup, user)
            except:
                # removes the user from the password file
                self.DeleteUserPassword(config, user)
                failedUserArray.append(user)
                print "The htgroup file doesn't exist, please, try again\n"
        
            # delete instance of Webcontrol
            del output

        self.PrintFailedUsers(failedUserArray)

    def AddUserToWeb(self, config, utilityObject):
        """ Add the user to an existing web in the htgroup file """
        ## DEBUGGING
        if config['General']["debugLevel"] == '5':
            import pdb; pdb.set_trace()

        objectName = "Username? (q => finish) [q] "
        # grab single/multiple groupNames
        userList = utilityObject.GetObjectId(config, objectName)

        failedUserArray =[]
        for user in userList:
            # instantiate instance of output to grab a list of
            # vhosts that are available
            output = Webcontrol.ApacheFunc()

            # add user to htgroup file
            htgroup = self.BuildHtgroupFileName(config, utilityObject, output)

            try:
                # append the value of the user to the correct htgroup file
                self.HtgroupAppend(htgroup, user)
            except:
                # removes the user from the password file
                self.DeleteUserPassword(config, user)
                failedUserArray.append(user)
                print "The htgroup file doesn't exist, please, try again\n"
        
            # delete instance of Webcontrol
            del output

        self.PrintFailedUsers(failedUserArray)

    def DeleteUser(self, config, utilityObject):
        """ Delete the user from the database file """
        ## DEBUGGING
        if config['General']["debugLevel"] == '1':
            import pdb; pdb.set_trace()

        objectName = "Username? (q => finish) [q] "
        # grab single/multiple groupNames
        userList = utilityObject.GetObjectId(config, objectName)

        failedUserArray =[]
        for user in userList:
            # output list of virtual hosts
            output = Webcontrol.ApacheFunc()

            # add user to htgroup file
            htgroup = self.BuildHtgroupFileName(config, utilityObject, output)

            # set variable to the username we want to delete
            regTest = " " + user

            try:
                # open the htgroup file and delete the euid matching reg_test
                inputHtgroupFile = open(htgroup, 'r')
                outputHtgroupFile = open(htgroup + '.new', 'w')

                # let's erase the euid
                for search in inputHtgroupFile.xreadlines():
                    outputHtgroupFile.write(search.replace(regTest, ''))

                #close the htgroup files and rename file over old file
                inputHtgroupFile.close()
                outputHtgroupFile.close()
                os.rename(htgroup, htgroup + '.bak')
                os.rename(htgroup + '.new', htgroup)

                # removes the user from the password file
                self.DeleteUserPassword(config, user)
            except:
                self.DeleteUserPassword(config, user)
                failedUserArray.append(user)
                print "The htgroup file doesn't exist, please, try again\n"

            # delete instantiation object
            del output

        self.PrintFailedUsers(failedUserArray)
    
    def ChangePassword(self, config, utilityObject, user=""):
        """ Change the password of a specified user """
        ## DEBUGGING
        if config['General']["debugLevel"] == '5':
            import pdb; pdb.set_trace()

        if user == "":
            # set text for prompt
            objectName = "Username? (q => finish) [q] "
            # grab single/multiple groupNames
            userList = utilityObject.GetObjectId(config, objectName)
            for user in userList:
                # removes the user from the password file
                self.DeleteUserPassword(config, user)

                # changes the password
                self.DoChangePassword(config, utilityObject, user)
        else:
            # removes the user from the password file
            self.DeleteUserPassword(user, apacheDict, htgroupDict)

            # changes the password
            self.DoChangePassword(config, utilityObject, user)

        

    def ViewUserByWeb(self, config, utilityObject):
        """
        View webs to which the user has rights.
        """
        # grab a list of usernames
        objectName = "Username? (q => finish) [q] "
        # grab single/multiple groupNames
        userList = utilityObject.GetObjectId(config, objectName)

        for user in userList:
            print "\n" + user + " has rights to these webs: "
            path = htgroupDict["pathToHtgroupFile"]
            callGrep = "grep " + user + " " + path + "htgroup.* | grep -v bak"

            # print callGrep
            
            os.system(callGrep)

            print "\n"



    def ReportUsers(self, config):
        """ show all users in the database file """
        sourceFile = open(config['Htgroup']['Server' + config['Session']['Htgroup']['CurrentServer']]["pathToPasswordFile"], 'r')
        alllines = sourceFile.readlines()
        sourceFile.close()

        print "User List: "
        for eachline in alllines:
            userName = eachline.split(":")
            print userName[0]

    
    def HtgroupAppend(self, htgroup, user):
        """ Add a user to a group in the htgroup.vHost file """
        # open the htgroup file and append the values where appropriate
        source_file = open(htgroup, 'r')
        alllines = source_file.readlines()
        source_file.close()

        # Let's add them to a web in the htgroup file
        # we will loop it to help with the ease of use
        loop = "y"
        while loop != "n":
            for l in alllines:
                print l,
            webName = raw_input("\nEnter existing or new webname here: ")
            for eachline in alllines:
                pattern = '^' + webName + ":"
                m = re.match(pattern, eachline)
                addEntry = 0
                if m != None:
                    alllines.remove(eachline)
                    if eachline[-1]=='\n': eachline = eachline[:-1]
                    alllines.append(eachline + ' ' + user + '\n')
                    addEntry = addEntry + 1
                    break
            if addEntry == 0:
                alllines.append(webName + ':' + ' ' + user + '\n')

            alllines.sort()
            print alllines
            loop = raw_input("Would you like to add that user to another web? (y for yes, n for no): ")

	# rename the old file
	os.rename(htgroup, htgroup + '.bak')
	# open the destination file
	destination_file = open(htgroup, 'w')
	# write lines into file
	destination_file.writelines(alllines)
	# close the destination file
	destination_file.close()

    def DeleteUserPassword(self, config, user):
        """ Delete a user from the password file """
        # set variable to the username we want to delete
        regTest = user
        # open the password file to read into memory for action
        sourceFile = open(config['Htgroup']['Server' + config['Session']['Htgroup']['CurrentServer']]["pathToPasswordFile"], 'r')
        alllines = sourceFile.readlines()
        sourceFile.close()

        # this checks each line for a match of the regular expression
        # (username) and removes it from the list
        y = 0
        for eachline in alllines:
            pattern = '^' + regTest
            #print pattern
            m = re.match(pattern, eachline)
            if m != None:
                print eachline
                print y
                alllines.remove(eachline)
                break
            y = y + 1


        # rename the old file
        os.rename(config['Htgroup']['Server' + config['Session']['Htgroup']['CurrentServer']]["pathToPasswordFile"], config['Htgroup']["pathToPasswordFile"] + '.bak')
        destinationFile = open(config['Htgroup']['Server' + config['Session']['Htgroup']['CurrentServer']]["pathToPasswordFile"], 'w')

        # write linesi of new password file into file
        destinationFile.writelines(alllines)
        destinationFile.close()

    def DoChangePassword(self, config, utilityObject, user=""):
        """ Change a user's password """
        # create and test new password
        genRandomPassword = raw_input("Generate Random Password? ([y]/n) ")
        if genRandomPassword == "":
            genRandomPassword = "y"

        if genRandomPassword == "y":
            pw = utilityObject.GeneratePassword(config)
            newPassword = pw
        else:
            newPassword = raw_input("Enter New Password: " )

        addUser = config['Htgroup']['Server' + config['Session']['Htgroup']['CurrentServer']]["pathToHtpasswd"] + " -b " + config['Htgroup']["pathToPasswordFile"] + " " + user + " " + newPassword
        if config['General']["debugLevel"] == '1':
            print addUser
        os.system(addUser)

        password_source_file = open(config['Htgroup']['Server' + config['Session']['Htgroup']['CurrentServer']]["pathToPasswordFile"], 'r')
        password_alllines = password_source_file.readlines()
        password_source_file.close()

        password_alllines.sort()

        # rename the old file
        os.rename(config['Htgroup']['Server' + config['Session']['Htgroup']['CurrentServer']]["pathToPasswordFile"], config['Htgroup']["pathToPasswordFile"] + '.bak')
        # open the destination file
        password_destination_file = open(config['Htgroup']['Server' + config['Session']['Htgroup']['CurrentServer']]["pathToPasswordFile"], 'w')
        # write lines into file
        password_destination_file.writelines(password_alllines)
        # close the destination file
        password_destination_file.close()

    def BuildHtgroupFileName(self, config, utilityObject, output):
        """ This function requests an fqdn from the user, then tests
        to see if the htgroup file for this vhost exists """

        # ask if the user wants to view the vhosts
        viewVhost = raw_input("Would you like to view a list of available virtual hosts? ([y]/n) ")
        # we check for an empty string, and set the default to yes
        if viewVhost == "":
            viewVhost = "y"

        # now we grab the vhost fqdn and test to see if the file exists
        if viewVhost == "y":
            vHostNameSuffix = output.OutputVhostList(config, utilityObject)
        else:
            vHostNameSuffix = raw_input("Enter FQDN here: ")

        # replace dots with underscores
        vHostNameSuffix = vHostNameSuffix.replace(".", "_")
        htgroup = config['Htgroup']['Server' + config['Session']['Htgroup']['CurrentServer']]["pathToHtgroupFile"] + "htgroup." + vHostNameSuffix

        return htgroup


    def PrintFailedUsers(self, failedUserArray):
        # print list of failed users
        if len(failedUserArray) > 0:
            print "Failed to add the following users: "
            for u in failedUserArray:
                print u,
            print "\nPlease run the current function again to correct any problems."
